package com.dx.mes.service.process.service;

import static com.dx.mes.common.bean.def.GenericDef.EVT_PUSH;
import static com.dx.mes.common.bean.def.GenericDef.E_FIPINQSHT_INVALID_INPUT;
import static com.dx.mes.common.bean.def.GenericDef.PROC_IN_PROCESS;
import static com.dx.mes.common.bean.def.GenericDef.RETURN_CODE_OK;
import static com.dx.mes.common.bean.def.GenericDef.RETURN_CODE_SET_ERROR;
import static com.dx.mes.common.bean.def.GenericDef.RETURN_CODE_UNKNOWN;
import static com.dx.mes.common.bean.def.GenericDef.RETURN_MESG_OK;
import static com.dx.mes.common.bean.def.GenericDef.TRX_OUT;
import static com.dx.mes.common.bean.def.GenericDef._NO;
import static com.dx.mes.common.bean.def.GenericDef._SPACE;
import static com.dx.mes.common.bean.def.GenericDef._YES;
import static com.dx.mes.common.bean.def.GenericDef.E_BIS_OPE;
import static com.dx.mes.common.bean.def.GenericDef.E_BIS_TOOL;
import static com.dx.mes.common.bean.def.GenericDef.E_READ_NOT_FOUND;
import static com.dx.mes.common.bean.def.GenericDef.T_FPPPRDOTIN;
import static com.dx.mes.common.bean.def.GenericDef.E_FPPPRDOTIN_STATUS_INVALID;
import static com.dx.mes.common.bean.def.GenericDef.E_FPPPRDOTIN_PRD_IS_OUT;
import static com.dx.mes.common.bean.def.GenericDef.E_FPPPRDOTIN_IP_ADDRESS_INVALID;

import java.sql.Timestamp;
import java.util.Date;
import java.util.UUID;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import com.dx.common.table.ppt.Bis_ope;
import com.dx.common.table.ppt.Bis_opeId;
import com.dx.common.table.ppt.Bis_tool;
import com.dx.common.table.ppt.Ret_prd_info;
import com.dx.common.table.ppt.Ret_prd_pos;
import com.dx.common.table.ppt.Ret_tool_st;
import com.dx.mes.common.dao.IBisOpeDao;
import com.dx.mes.common.dao.IBisToolDao;
import com.dx.mes.common.dao.IRetPrdInfoDao;
import com.dx.mes.common.dao.IRetToolStDao;
import com.dx.mes.common.dao.IRetWorkPosDao;
import com.dx.mes.common.transcoder.util.AppContext;
import com.dx.mes.common.transcoder.util.GUIDGenerator;
import com.dx.mes.common.transcoder.util.JacksonUtil;
import com.dx.mes.common.transcoder.util.LogUtils;
import com.dx.mes.common.transcoder.util.Util;
import com.dx.mes.facade.process.service.IFppprdoutinService;
import com.dx.mes.facade.process.tx.fppprdoutin.FppprdoutinI;
import com.dx.mes.facade.process.tx.fppprdoutin.FppprdoutinO;

/**
 * Created by tl on 2017/6/30.
 */
@Service("fppprdoutinService")
public class FppprdoutinService implements IFppprdoutinService {

    private LogUtils logUtils;
    private static final String TX_NAME = T_FPPPRDOTIN;

    @Autowired
    private IRetPrdInfoDao retPrdInfoDao;
    @Autowired
    private IBisToolDao bisToolDao;
    @Autowired
    private IRetToolStDao retToolStDao;
    @Autowired
    private IBisOpeDao bisOpeDao;
    @Autowired
    private IRetWorkPosDao retWorkPosDao;


    @Override
    public String subMainProc(String evt_no, String strInMsg) {
        AppContext.clear();
        AppContext.setCurrServiceName(FppprdoutinService.class.getSimpleName());
        AppContext.setCurrEventNumber(evt_no);
        logUtils = new LogUtils(FppprdoutinService.class);
        logUtils.info("[InTrx:" + strInMsg + "]");
//		Session session = retPrdInfoDao.getCrSession();

        String outMsg = "";
        FppprdoutinI inTrx = new FppprdoutinI();
        FppprdoutinO outTrx = new FppprdoutinO();

        outTrx.setTrx_id(TX_NAME);
        outTrx.setType_id(TRX_OUT);
        outTrx.setRtn_code(String.valueOf(RETURN_CODE_SET_ERROR));

        try {
            inTrx = JacksonUtil.fromJson(strInMsg, FppprdoutinI.class);

            subMainProc2(inTrx.getAction_flg().toCharArray()[0],inTrx,outTrx);
            if (!outTrx.getRtn_code().equals(RETURN_CODE_OK)) {
                TransactionAspectSupport.currentTransactionStatus()
                        .setRollbackOnly();
            } else {
                retPrdInfoDao.flushCurSession();
            }
        } catch (Exception ex) {
            outTrx.setRtn_mesg(ex.toString());
            outTrx.setRtn_code(RETURN_CODE_UNKNOWN);
            logUtils.error(Util.stackTraceToString(ex));
            TransactionAspectSupport.currentTransactionStatus()
                    .setRollbackOnly();
        } finally {
            outMsg = JacksonUtil.toJSONStr(outTrx);
            logUtils.info("[OutTrx:" + outTrx + "]");
        }
        return outMsg;
    }

    private void subMainProc2(char actionType,FppprdoutinI inTrx,FppprdoutinO outTrx) {

        switch (actionType) {
            case 'R': {
                manuallyRemoved(inTrx,outTrx);//手动取出
                break;
            }
            case 'I': {
                manuallyInto(inTrx,outTrx);//手动放入
                break;
            }

            default: {
                String gszMsgBuf = "Invalide type input: [" + actionType + "]";
                outTrx.setRtn_code(String.valueOf(E_FIPINQSHT_INVALID_INPUT));
                outTrx.setRtn_mesg(gszMsgBuf);
                return;
            }
        }
    }

    /**
     * 手动将玻璃从机台中取出，并放入offline机台
     * @param inTrx
     * @param outTrx
     */
    private void manuallyRemoved(FppprdoutinI inTrx, FppprdoutinO outTrx) {
     /*   1.手动取出check条件*/
        String sheet_id = inTrx.getSheet_id();
        String ope_ids = inTrx.getOpe_info();
        String[] split = ope_ids.split("@");
        //站点加版本
        String ope_id = split[0];
        String ope_ver = split[1];
        String tool_id = inTrx.getTool_id();
        Ret_prd_info ret_prd_info = retPrdInfoDao.get(sheet_id);
        Bis_opeId bis_opeId = new Bis_opeId(ope_id, ope_ver);
        Bis_ope bis_ope = bisOpeDao.get(bis_opeId);

        if (bis_ope == null) {
            outTrx.setRtn_code(E_BIS_OPE + E_READ_NOT_FOUND+"");
            outTrx.setRtn_mesg("系统中未维护该站点"+ope_id+ope_ver+"，请确认");
            return;
        }
        Bis_tool bis_tool = bisToolDao.get(tool_id);
        if (bis_tool == null) {
            outTrx.setRtn_code(E_BIS_TOOL + E_READ_NOT_FOUND+"");
            outTrx.setRtn_mesg("系统中未维护该设备"+tool_id+"，请确认");
            return;
        }
        //1.1 玻璃状态是否为INPR
        if(!ret_prd_info.getPrd_stat().equals(PROC_IN_PROCESS)){
        	 outTrx.setRtn_code(E_FPPPRDOTIN_STATUS_INVALID +"");
             outTrx.setRtn_mesg("玻璃状态不是[INPR],不可以做此操作！");
             return;
        }
        //1.2 判断玻璃是否已经被取出
        if(StringUtils.isNotEmpty(ret_prd_info.getPrd_in_out_flg()) && ret_prd_info.getPrd_in_out_flg().equals(_YES)){
        	outTrx.setRtn_code(E_FPPPRDOTIN_PRD_IS_OUT+"");
            outTrx.setRtn_mesg("玻璃已经被手动取出，无需再次取出");
            return;
        }
        
        Bis_tool bis_tool_cr = bisToolDao.get(ret_prd_info.getCr_tool_id_fk());
        Ret_tool_st ret_tool_st = retToolStDao.get(tool_id);
        //1.3 判断玻璃所在机台IP与维护的IP是否一致
        if(StringUtils.isEmpty(bis_tool_cr.getTool_ip()) || !bis_tool_cr.getTool_ip().trim().equals(inTrx.getIp_address().trim())){
        	 outTrx.setRtn_code(E_FPPPRDOTIN_IP_ADDRESS_INVALID +"");
             outTrx.setRtn_mesg("玻璃不在该机台，请去对应的机台进行操作");
             return;
        }
        
        //1.4 更新信息
        Timestamp gEvtTimestamp = Util.getCurrentTimestamp();
        
        ret_prd_info.setSv_tool_id_fk(ret_prd_info.getCr_tool_id_fk());
        ret_prd_info.setSv_tool_run_mode(ret_prd_info.getCr_tool_run_mode());
        ret_prd_info.setSv_ope_id_fk(ret_prd_info.getCr_ope_id_fk());
        ret_prd_info.setSv_ope_ver_fk(ret_prd_info.getCr_ope_ver_fk());
        ret_prd_info.setSv_ope_no_fk(ret_prd_info.getCr_ope_no_fk());
        ret_prd_info.setSv_proc_id_fk(ret_prd_info.getCr_proc_id_fk());
        
        ret_prd_info.setTool_id_fk(tool_id);
        ret_prd_info.setCr_tool_run_mode(ret_tool_st.getTool_run_mode());
        ret_prd_info.setCr_ope_id_fk(ope_id);
        ret_prd_info.setCr_ope_no_fk(ope_id);
        ret_prd_info.setCr_ope_ver_fk(ope_ver);
        ret_prd_info.setCr_proc_id_fk(bis_ope.getProc_id());
        
        ret_prd_info.setPrd_in_out_flg(_YES);
        ret_prd_info.setEvt_usr(inTrx.getEvt_user());
        ret_prd_info.setEvt_timestamp(gEvtTimestamp);
        ret_prd_info.setEvt_cate(EVT_PUSH);
        retPrdInfoDao.update(ret_prd_info);
        
        //1.5 在RET_PRD_POS增加一笔数据
        saveToPos(sheet_id, tool_id, gEvtTimestamp, inTrx.getEvt_user());
        
        outTrx.setRtn_code(RETURN_CODE_OK);
        outTrx.setRtn_mesg(RETURN_MESG_OK);

    }


	/**
	 * 手动将玻璃放入机台
	 * @param inTrx
	 * @param outTrx
	 */
    private void manuallyInto(FppprdoutinI inTrx, FppprdoutinO outTrx) {
        String sheet_id = inTrx.getSheet_id();
        Ret_prd_info ret_prd_info = retPrdInfoDao.get(sheet_id);
        Bis_tool bis_tool = bisToolDao.get(ret_prd_info.getSv_tool_id_fk());
        
      //1.1 玻璃状态是否为INPR
        if(!ret_prd_info.getPrd_stat().equals(PROC_IN_PROCESS)){
        	 outTrx.setRtn_code(E_FPPPRDOTIN_STATUS_INVALID +"");
             outTrx.setRtn_mesg("玻璃状态不是[INPR],不可以做此操作！");
             return;
        }
        //1.2 判断玻璃是否已经被取出
        if(StringUtils.isEmpty(ret_prd_info.getPrd_in_out_flg()) || !ret_prd_info.getPrd_in_out_flg().equals(_YES)){
        	outTrx.setRtn_code(E_FPPPRDOTIN_PRD_IS_OUT+"");
            outTrx.setRtn_mesg("玻璃在机台中，未被取出，不可以做放回动作！");
            return;
        }
        //1.3 判断玻璃所在机台IP与维护的IP是否一致
        if( StringUtils.isEmpty(bis_tool.getTool_ip()) || ! bis_tool.getTool_ip().trim().equals(inTrx.getIp_address().trim()) ){
        	 outTrx.setRtn_code(E_FPPPRDOTIN_IP_ADDRESS_INVALID +"");
             outTrx.setRtn_mesg("玻璃不在该机台，请去对应的机台进行操作");
             return;
        }
        
        //更新信息
        Timestamp gEvtTimestamp = Util.getCurrentTimestamp();
        ret_prd_info.setTool_id_fk(ret_prd_info.getPv_tool_id_fk());
        ret_prd_info.setCr_tool_run_mode(ret_prd_info.getPv_tool_run_mode());
        ret_prd_info.setCr_ope_id_fk(ret_prd_info.getSv_ope_id_fk());
        ret_prd_info.setCr_ope_ver_fk(ret_prd_info.getSv_ope_ver_fk());
        ret_prd_info.setCr_ope_no_fk(ret_prd_info.getSv_ope_no_fk());
        ret_prd_info.setCr_proc_id_fk(ret_prd_info.getSv_proc_id_fk());
        ret_prd_info.setCr_toolg_id_fk(ret_prd_info.getSv_toolg_id_fk());
        
        ret_prd_info.setSv_tool_id_fk(_SPACE);
        ret_prd_info.setSv_tool_run_mode(_SPACE);
        ret_prd_info.setSv_toolg_id_fk(_SPACE);
        ret_prd_info.setSv_ope_id_fk(_SPACE);
        ret_prd_info.setSv_ope_ver_fk(_SPACE);
        ret_prd_info.setSv_ope_no_fk(_SPACE);
        
        ret_prd_info.setPrd_in_out_flg(_NO);
        ret_prd_info.setEvt_timestamp(gEvtTimestamp);
        ret_prd_info.setEvt_usr(inTrx.getEvt_user());
        ret_prd_info.setEvt_cate(EVT_PUSH);
        retPrdInfoDao.update(ret_prd_info);
        
        //在RET_PRD_POS增加一笔数据
        saveToPos(sheet_id, bis_tool.getTool_id(), gEvtTimestamp, inTrx.getEvt_user());
        outTrx.setRtn_code(RETURN_CODE_OK);
        outTrx.setRtn_mesg(RETURN_MESG_OK);


    }
    //【通用】无论放入还是取出都需要在pos表新增一条信息
    private void saveToPos(String sheet_id,String tool_id,Timestamp gEvtTimestamp, String evt_usr){
    	String evt_seq_id = GUIDGenerator.javaGUID();   
        Ret_prd_pos ret_prd_pos = new Ret_prd_pos();
        ret_prd_pos.setEvent_seq_id(evt_seq_id);
        ret_prd_pos.setPrd_seq_id_fk(sheet_id);
        ret_prd_pos.setTool_id_fk(tool_id);
        ret_prd_pos.setLine_id(tool_id);
        ret_prd_pos.setEvt_usr(evt_usr);
        ret_prd_pos.setEvt_timestamp(gEvtTimestamp);
        retWorkPosDao.save(ret_prd_pos);
    }

}
